package cn.tedu.mall.seckill.service.Impl;

import cn.tedu.mall.pojo.seckill.dto.SeckillOrderAddDTO;
import cn.tedu.mall.pojo.seckill.vo.SeckillCommitVO;
import cn.tedu.mall.seckill.interceptor.SeckillInterceptor;
import cn.tedu.mall.seckill.service.ISeckillService;
import com.alibaba.fastjson.JSON;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

/**
 * @author zhangyiping
 * @date 2024/1/23
 */
@Service
public class SeckillServiceImpl implements ISeckillService {

    @Autowired
    private List<SeckillInterceptor> seckillInterceptors;// 注入的顺序严格按照Order注解设置的值

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    /**
     * 1、校验 randCode 是否与当初初始化预热spu数据是生成的随机url中的随机码对应
     * 2、防止同一个用户抢购下单同一个spuId多次
     * 3、执行redis减库存，只要返回值不是负数就验证通过（redis的操作是原子性的）
     * 4、发送一个消息到订单新增的队列中，由订单系统的消费者实现异步下单
     * @param seckillOrderAddDTO
     * @return
     */
    @Override
    public SeckillCommitVO commitSeckill(SeckillOrderAddDTO seckillOrderAddDTO) {
        // 循环拦截器，依次调用check方法
        for (SeckillInterceptor seckillInterceptor : seckillInterceptors) {
            seckillInterceptor.seckillCommitCheck(seckillOrderAddDTO);
        }
        // 准备消息String类型的json字符串
        String msg = JSON.toJSONString(seckillOrderAddDTO);
        // 发送消息（为了复用消费逻辑，直接往csmall-order模块中的队列主题里发送，为了区分这个秒杀下单，tag携带seckillAdd）
        SendResult sendResult = rocketMQTemplate.syncSend("csmall-order-add-topic:seckillAdd", msg);
        // 根据发送结果，返回数据
        if (sendResult.getSendStatus().toString().equals("SEND_OK")) {
            SeckillCommitVO seckillCommitVO = new SeckillCommitVO();
            // seckillCommitVO.setId(seckillCommitVO.getId());
            seckillCommitVO.setSn(seckillOrderAddDTO.getSn());
            seckillCommitVO.setPayAmount(seckillOrderAddDTO.getAmountOfActualPay());
            seckillCommitVO.setCreateTime(LocalDateTime.now());
            return seckillCommitVO;
        }
        return null;
    }
}
